part of '../repository.dart';

const _kAdverbTypeValue = 'adverb';

class _AdverbDto extends Equatable implements _WordDto {
  const _AdverbDto._internal({
    required this.id,
    required this.title,
    required this.translationDtoMap,
    required this.transcriptionDtoMap,
    required this.definition,
    required this.useCaseDtos,
    required this.imageId,
    required this.rank,
    required this.tagsDto,
  });

  @override
  final String id;

  @override
  final String title;

  @override
  final BuiltMap<_LearningLocaleDto, String> translationDtoMap;

  @override
  final BuiltMap<_DialectDto, String> transcriptionDtoMap;

  @override
  final String definition;

  @override
  final BuiltList<_UseCaseDto> useCaseDtos;

  @override
  final String? imageId;

  @override
  final int? rank;

  @override
  final _WordTagsDto tagsDto;

  @override
  String get type => _kAdverbTypeValue;

  @override
  List<Object?> get props {
    return [
      id,
      title,
      translationDtoMap,
      transcriptionDtoMap,
      definition,
      useCaseDtos,
      imageId,
      rank,
      tagsDto,
    ];
  }

  factory _AdverbDto.fromJson(Map<String, dynamic> json) {
    final transcriptionMap = json[_kLexicalItemTranscriptionsKey] as Map;

    final transcriptionDtoMap = transcriptionMap.map((dialectString, transcription) {
      final dialectDto = _DialectDto.fromString(dialectString);
      return MapEntry(dialectDto, transcription as String);
    }).build();

    final translationMap = json[_kLexicalItemTranslationsKey] as Map;

    final translationDtoMap = translationMap.map((learningLocaleString, translation) {
      final learningLocaleDto = _LearningLocaleDto.fromString(learningLocaleString);
      return MapEntry(learningLocaleDto, translation as String);
    }).build();

    final useCaseMaps = List.castFrom<dynamic, Map>(json[_kLexicalItemUseCasesKey]);

    final useCaseDtos = useCaseMaps.map((useCaseMap) {
      final useCaseJson = Map.castFrom<dynamic, dynamic, String, dynamic>(useCaseMap);
      return _UseCaseDto.fromJson(useCaseJson);
    }).toBuiltList();

    final tagsMap = json[_kWordTagsKey] as Map;

    final tagsJson = Map.castFrom<dynamic, dynamic, String, dynamic>(tagsMap);

    final tagsDto = _WordTagsDto.fromJson(tagsJson);

    return _AdverbDto._internal(
      id: json[_kLexicalItemIdKey],
      title: json[_kLexicalItemTitleKey],
      translationDtoMap: translationDtoMap,
      transcriptionDtoMap: transcriptionDtoMap,
      definition: json[_kLexicalItemDefinitionKey],
      useCaseDtos: useCaseDtos,
      imageId: json[_kLexicalItemImageIdKey],
      rank: json[_kWordRankKey],
      tagsDto: tagsDto,
    );
  }

  factory _AdverbDto.fromEntity(Adverb adverb) {
    final transcriptionDtoMap = adverb.transcriptions.map((dialect, transcription) {
      final dialectDto = _DialectDto.fromEntity(dialect);
      return MapEntry(dialectDto, transcription);
    });

    final translationDtoMap = adverb.translations.map((learningLocale, translation) {
      final learningLocaleDto = _LearningLocaleDto.fromEntity(learningLocale);
      return MapEntry(learningLocaleDto, translation);
    });

    final useCaseDtos = adverb.useCases.map((useCase) {
      return _UseCaseDto.fromEntity(useCase);
    }).toBuiltList();

    final tagsDto = _WordTagsDto.fromEntity(adverb.tags);

    return _AdverbDto._internal(
      id: adverb.id,
      title: adverb.title,
      translationDtoMap: translationDtoMap,
      transcriptionDtoMap: transcriptionDtoMap,
      definition: adverb.definition,
      useCaseDtos: useCaseDtos,
      imageId: adverb.imageId,
      rank: adverb.rank,
      tagsDto: tagsDto,
    );
  }

  @override
  Map<String, dynamic> toJson() {
    final transcriptionJson = transcriptionDtoMap.map((dialectDto, transcription) {
      return MapEntry(dialectDto.toString(), transcription);
    }).toMap();

    final translationJson = translationDtoMap.map((learningLocaleDto, translation) {
      return MapEntry(learningLocaleDto.toString(), translation);
    }).toMap();

    final useCaseJsons = useCaseDtos.map((useCaseDto) {
      return useCaseDto.toJson();
    }).toList();

    final json = <String, dynamic>{
      _kLexicalItemTypeKey: type,
      _kLexicalItemIdKey: id,
      _kLexicalItemTitleKey: title,
      _kLexicalItemTranslationsKey: translationJson,
      _kLexicalItemTranscriptionsKey: transcriptionJson,
      _kLexicalItemDefinitionKey: definition,
      _kLexicalItemUseCasesKey: useCaseJsons,
      _kLexicalItemImageIdKey: imageId,
      _kWordRankKey: rank,
      _kWordTagsKey: tagsDto.toJson(),
    };

    return json;
  }

  @override
  Adverb toEntity() {
    final transcriptions = transcriptionDtoMap.map((dialectDto, transcription) {
      return MapEntry(dialectDto.toEntity(), transcription);
    });

    final translations = translationDtoMap.map((learningLocaleDto, translation) {
      return MapEntry(learningLocaleDto.toEntity(), translation);
    });

    final useCases = useCaseDtos.map((useCaseDto) {
      return useCaseDto.toEntity();
    }).toBuiltList();

    return Adverb(
      id: id,
      title: title,
      translations: translations,
      transcriptions: transcriptions,
      definition: definition,
      useCases: useCases,
      imageId: imageId,
      rank: rank,
      tags: tagsDto.toEntity(),
    );
  }
}
